R을 이용한 데이터 전처리와 시각화 기초 코스

Author

waterfirst

1 Introduction

이 수업은 코딩을 전혀 모르는 사람들을 대상으로 숫자로 된 데이터를 적절히 칼질하여 요리할 수 있도록 하는 것을 목적으로 만들었습니다.

반복적으로 정형화된 데이터를 처리하고 그래프를 그리는 연구원들은 최종적으로는 자신의 결과물을 알기 쉽게 표현하는 것입니다.

이를 위해 tidyverse 패키지 하나만으로 얼마나 쉽게 데이터를 다룰 수 있는지 R의 장점이 무엇인지 알 수 있는 시간이 될 것입니다.

R 언어 간단 소개

두명의 뉴질랜드 통계학자가 만듦 : 로버트 젠틀맨(Robert Gentleman)과 로스 이하카(Ross Ihaka)

해들리 위컴에 의해 빅데이터 툴로 발전함 (대표적 : ggplot, tidyverse)

언어의 특징

1부터 시작 (다른 언어들은 0부터 시작)

패키지 설치, 불러오기

  • install.packages(“패키지이름”)

  • library(패키지이름)

프로그램 구분

Back end를 담당하는 데이터 전처리 및 시각화는 tidyverse 패키지를 이용하여 진행하고 필요할 경우, 추가 패키지를 이용할 것입니다.

실전에서 바로 쓸 수 있도록 기본 예제 데이터를 이용하여 학습하고 각자 자신의 자주 사용하는 데이터를 이용하여 반복 적으로 하던 일을 코딩을 통해 줄이고 더 창의적인 일에 시간을 쓸 수 있도록 4주 과정으로 만들었습니다. (주1회 2~3시간)


2 강의순서

  1. R 설치, 기본문법 (1주차)

    https://dplyr.tidyverse.org/articles/dplyr.html

  2. 데이터 전처리 문제 풀이 (2주차)

    https://m-clark.github.io/data-processing-and-visualization/intro.html

  3. 데이터 전처리 및 시각화 (3주차)

    https://r-graph-gallery.com/

  4. 다양한 데이터 시각화 연습 (4주차)

    2d, 3d 이미지화


3 강의전 사전 준비

(#1~3까지 하고, #4~7은 나중에~~)

  1. R 설치 : https://posit.co/download/rstudio-desktop/

  2. RStudio 설치 https://posit.co/download/rstudio-desktop/

  3. Quarto CLI설치 : https://quarto.org/docs/download/

  4. Latex 설치 : (Rstudio 터미널창) $ quarto install tinytex

  5. 출판용 사이트 가입 : https://quartopub.com/

  6. github 가입 : https://github.com/

  7. git 설치 : https://git-scm.com/download/win

[Quarto ]https://quarto.org/docs/presentations/revealjs/

프로그램을 배울 때, 다운로드, 설치, 환경설정만 하면 50%는 이미 배운것입니다. ^^

RStudio 설명

4 Day1

  • 데이터 분석과 시각화를 하는데 R이 최선인가?

ex) 상용 프로그램 : 엑셀 , 미니탭, 오리진, 매트랩, 스팟파이어

오픈소스 : 파이썬, R

  • 왜 데이터 분석 및 시각화가 필요한가? GPT 시대인데…

  • 내가 하고 있는 분야에 데이터는 정형화된 데이터인가?(숫자) 아니면 비정형 데이터인가(문자)

  • 데이터 분석의 최종 목적은 무엇인가?


4-1. R Basic

1. 데이터 형식

숫자형(numeric) : num(숫자형), int(정수형), dbl(실수형)
문자형(character) : chr
범주형(factor) : fct
논리형(logical) : logi
결측 (Not Available) : NA
무한대 (Infinite) : Inf
데이터 형식 알아보기 : class(변수명) is.numeric(변수명), is.character(변수명), is.factor(변수명)
데이터 형식 바꾸기 : as.numeric(변수명), as.factor(변수명), as.character(변수명), as.logical(변수명)
Note

범주형 변수(factor) : 그래프를 그리거나 통계적 분석시 유용함

데이터를 열별로 모아 놓은 dataframe, tibble 이 실제 분석에 이용

list, matrix, array 형태도 있음


2. 자주 사용 하는 함수

평균(mean) : mean(변수)
중위수(median) : median(변수)
최대값(max) : max(변수)
최소값(min) : min(변수)
합(sum) : sum(변수)
표준편차(sd) : sd(변수)
분산(var) : var(변수)
절대값(abs) : abs(변수)
반올림(round) : round(변수, 반올림할 소수점 아래수)
제곱근(sqrt) : sqrt(변수)
원소갯수, 문자열길이(length) : length(변수)
행, 열의 수(dim) : dim(df)
프린트(print) : print(변수) / print(“문자”)
조건(ifelse) : ifelse(x>10, “a”, “b”)
중복없이 관측치 종류(unique) : unique(변수)
문자패턴 찾기(grep, grepl) : grep(“문자”, df):열번호 출력, grepl(“문자”, df):true/false로 출력
문자패턴 찾아 바꾸기(gsub) : gsub(“이전문자”, “새로운 문자”, df)
열갯수(ncol) : ncol(df)
행갯수(nrow) : nrow(df)
열이름(colnames) : colnames(df)
행이름(colnames) : rownames(df)
빈도수 구하기(table) : table(변수)
정렬하기(sort) : 내림차순 sort(변수), 오름차순 sort(변수, decreasing = TRUE)
열이름(names, colnames) : names(변수)
최대, 최소위치 찾기(which.max, which.min) : which.max(변수), which.min(변수)
4-2. 데이터 탐색 기본 함수

head : 앞 6개 행 보기

tail : 뒤 6개 행 보기

summary : 기술 통계 간단히 보기

str : 데이터 형식 보기


3. 연산 기호

"
* (곱하기) : x*2
/ (나누기) : x/2
%/% (나눗셈의 몫) : 16%/%3 = 5
%% (나눗셈의 나머지) : 16%/%3 = 1
== (일치, True or False) : 3==5, False
!= (불일치) : 3!=5, True
& (and) : x > 2 & x < 10
| (or) : x < 2 | x > 10
"


4-3. Tidyverse

[참고 자료]https://rstudio.github.io/cheatsheets/html/data-transformation.html

%>% (파이프라인, 왼쪽 데이터프레임을 오른쪽 함수에 넣어라) : df %>% head()

filter (조건에 맞는 행 추출) : df %>% filter(컬럼명 == “a”)

select(특정열 선택) : df %>% select(열번호) / df[, 열번호]

slice(특정행 선택) : df %>% slice(행번호) / df[행번호, ]
mutate(특정열 추가) : df %>% mutate(새로운 열이름 = )
rename(열이름 바꾸기) : df %>% rename(새로운 열이름 = 이전 열이름)
arrange(정렬하기) : 오름차순 : df %>% arrange(열이름), 내림차순 : df %>% arrange(desc(열이름))

group_by(특정열 그룹화), summarise(통계치 계산) :

df %>% group_by(열이름) %>% summarise(평균=mean(열이름))
열합치기(inner_join, full_join, left_join, right_join) : inner_join(df1, df2, by=“name”)

separate(특정기호로 분리) : df %>% separate(열이름, into = c("a", "b"), sep = "_")

na가 있는 행 제거하기(na.omit) : na.omit(df)

na가 있는 열에서 na 는 제거하고 계산하기 (na.rm=T) : mean(df, na.rm=T)

열합치기(cbind, bind_cols) : cbind(df1, df2) or bind_cols(df1, df2)
행합치기(rbind, bind_rows) : rbind(df1, df2) or bind_rows(df1, df2)

중복없는 값 찾기(distinct) : df %>% distinct ("열이름")

행의 수 세기 : n(), count()

4-4. long_form, wide_form

iris data를 이용하여 꽃잎 길이, 넓이, 꽃받임 길이, 넓이를 long form으로 바꾸어보자.

Code
library(tidyverse)
head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
Code
iris |> pivot_longer(cols = Sepal.Length:Petal.Width, names_to = "measure", values_to = "value") |> head()
# A tibble: 6 × 3
  Species measure      value
  <fct>   <chr>        <dbl>
1 setosa  Sepal.Length   5.1
2 setosa  Sepal.Width    3.5
3 setosa  Petal.Length   1.4
4 setosa  Petal.Width    0.2
5 setosa  Sepal.Length   4.9
6 setosa  Sepal.Width    3  
Code
iris |> pivot_longer(cols = Sepal.Length:Petal.Width, 
                     names_to = c("name1", "name2"),
                     names_sep ='\\.') |> head()
# A tibble: 6 × 4
  Species name1 name2  value
  <fct>   <chr> <chr>  <dbl>
1 setosa  Sepal Length   5.1
2 setosa  Sepal Width    3.5
3 setosa  Petal Length   1.4
4 setosa  Petal Width    0.2
5 setosa  Sepal Length   4.9
6 setosa  Sepal Width    3  
Code
iris_long <- 
  iris |> pivot_longer(cols = Sepal.Length:Petal.Width, names_to = "measure", values_to = "value")


iris_long |> pivot_wider(
    names_from = measure,  values_from = value) |> unnest() |> head()
# A tibble: 6 × 5
  Species Sepal.Length Sepal.Width Petal.Length Petal.Width
  <fct>          <dbl>       <dbl>        <dbl>       <dbl>
1 setosa           5.1         3.5          1.4         0.2
2 setosa           4.9         3            1.4         0.2
3 setosa           4.7         3.2          1.3         0.2
4 setosa           4.6         3.1          1.5         0.2
5 setosa           5           3.6          1.4         0.2
6 setosa           5.4         3.9          1.7         0.4


4-4. 연습문제

  • palmer penguin을 df에 넣고 앞 6개 행을 살펴보라.

    Code
    #install.packages("palmerpenguins")
    library(palmerpenguins)
    df <-  penguins
    head(df)
    # A tibble: 6 × 8
      species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
      <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
    1 Adelie  Torgersen           39.1          18.7               181        3750
    2 Adelie  Torgersen           39.5          17.4               186        3800
    3 Adelie  Torgersen           40.3          18                 195        3250
    4 Adelie  Torgersen           NA            NA                  NA          NA
    5 Adelie  Torgersen           36.7          19.3               193        3450
    6 Adelie  Torgersen           39.3          20.6               190        3650
    # ℹ 2 more variables: sex <fct>, year <int>
  • 데이터 탐색을 하라 (EDA : str, summary 이용)

    Code
    str(df)
    tibble [344 × 8] (S3: tbl_df/tbl/data.frame)
     $ species          : Factor w/ 3 levels "Adelie","Chinstrap",..: 1 1 1 1 1 1 1 1 1 1 ...
     $ island           : Factor w/ 3 levels "Biscoe","Dream",..: 3 3 3 3 3 3 3 3 3 3 ...
     $ bill_length_mm   : num [1:344] 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42 ...
     $ bill_depth_mm    : num [1:344] 18.7 17.4 18 NA 19.3 20.6 17.8 19.6 18.1 20.2 ...
     $ flipper_length_mm: int [1:344] 181 186 195 NA 193 190 181 195 193 190 ...
     $ body_mass_g      : int [1:344] 3750 3800 3250 NA 3450 3650 3625 4675 3475 4250 ...
     $ sex              : Factor w/ 2 levels "female","male": 2 1 1 NA 1 2 1 2 NA NA ...
     $ year             : int [1:344] 2007 2007 2007 2007 2007 2007 2007 2007 2007 2007 ...
    Code
    summary(df)
          species          island    bill_length_mm  bill_depth_mm  
     Adelie   :152   Biscoe   :168   Min.   :32.10   Min.   :13.10  
     Chinstrap: 68   Dream    :124   1st Qu.:39.23   1st Qu.:15.60  
     Gentoo   :124   Torgersen: 52   Median :44.45   Median :17.30  
                                     Mean   :43.92   Mean   :17.15  
                                     3rd Qu.:48.50   3rd Qu.:18.70  
                                     Max.   :59.60   Max.   :21.50  
                                     NA's   :2       NA's   :2      
     flipper_length_mm  body_mass_g       sex           year     
     Min.   :172.0     Min.   :2700   female:165   Min.   :2007  
     1st Qu.:190.0     1st Qu.:3550   male  :168   1st Qu.:2007  
     Median :197.0     Median :4050   NA's  : 11   Median :2008  
     Mean   :200.9     Mean   :4202                Mean   :2008  
     3rd Qu.:213.0     3rd Qu.:4750                3rd Qu.:2009  
     Max.   :231.0     Max.   :6300                Max.   :2009  
     NA's   :2         NA's   :2                                 
  • NA가 있는 열 확인하라

    Code
    colSums(is.na(df))
              species            island    bill_length_mm     bill_depth_mm 
                    0                 0                 2                 2 
    flipper_length_mm       body_mass_g               sex              year 
                    2                 2                11                 0 
  • 컬럼명에서 _mm 제거하고 6개 행 보기(rename 이용 )

    Code
    library(tidyverse)
    df |> rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      head()
    # A tibble: 6 × 8
      species island   bill_length bill_depth flipper_length body_mass_g sex    year
      <fct>   <fct>          <dbl>      <dbl>          <int>       <int> <fct> <int>
    1 Adelie  Torgers…        39.1       18.7            181        3750 male   2007
    2 Adelie  Torgers…        39.5       17.4            186        3800 fema…  2007
    3 Adelie  Torgers…        40.3       18              195        3250 fema…  2007
    4 Adelie  Torgers…        NA         NA               NA          NA <NA>   2007
    5 Adelie  Torgers…        36.7       19.3            193        3450 fema…  2007
    6 Adelie  Torgers…        39.3       20.6            190        3650 male   2007
  • Adelie 펭귄의 부리 길이 평균은 얼마일까?

    Code
    df |> 
       rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      filter(species =="Adelie")  |> 
      summarise("부리길이" = mean(bill_length, na.rm=T))
    # A tibble: 1 × 1
      부리길이
         <dbl>
    1     38.8
  • 각 펭귄의 부리 길이, 부리 높이의 평균 구하라(소수 첫째자리까지 구하라)

    Code
    df |> 
       rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      group_by(species) %>% summarise("부리길이"=round(mean(bill_length, na.rm=T),1), "부리높이"=round(mean(bill_depth, na.rm=T),1))
    # A tibble: 3 × 3
      species   부리길이 부리높이
      <fct>        <dbl>    <dbl>
    1 Adelie        38.8     18.3
    2 Chinstrap     48.8     18.4
    3 Gentoo        47.5     15  
  • 펭귄 종류별 몇마리인가

    Code
    df |> 
       rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      group_by(species) %>%
      summarise(n=n())
    # A tibble: 3 × 2
      species       n
      <fct>     <int>
    1 Adelie      152
    2 Chinstrap    68
    3 Gentoo      124
  • 펭귄종류, 부리길이, 부리높이 열만 선택해서 보여줘라 (6개 행)

    Code
    df |> 
       rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      select(species, bill_length, bill_depth) %>% head()
    # A tibble: 6 × 3
      species bill_length bill_depth
      <fct>         <dbl>      <dbl>
    1 Adelie         39.1       18.7
    2 Adelie         39.5       17.4
    3 Adelie         40.3       18  
    4 Adelie         NA         NA  
    5 Adelie         36.7       19.3
    6 Adelie         39.3       20.6
  • 10행에서 15행을 보여주라.

    Code
    df %>% slice(10:15)
    # A tibble: 6 × 8
      species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
      <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
    1 Adelie  Torgersen           42            20.2               190        4250
    2 Adelie  Torgersen           37.8          17.1               186        3300
    3 Adelie  Torgersen           37.8          17.3               180        3700
    4 Adelie  Torgersen           41.1          17.6               182        3200
    5 Adelie  Torgersen           38.6          21.2               191        3800
    6 Adelie  Torgersen           34.6          21.1               198        4400
    # ℹ 2 more variables: sex <fct>, year <int>
  • 새로운 변수를 만들어라 (bill_ratio = bill_lenght/bill_depth) : mutate

    Code
    df |> 
       rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      mutate(bill_ratio=bill_length/bill_depth) |> 
      head()
    # A tibble: 6 × 9
      species island   bill_length bill_depth flipper_length body_mass_g sex    year
      <fct>   <fct>          <dbl>      <dbl>          <int>       <int> <fct> <int>
    1 Adelie  Torgers…        39.1       18.7            181        3750 male   2007
    2 Adelie  Torgers…        39.5       17.4            186        3800 fema…  2007
    3 Adelie  Torgers…        40.3       18              195        3250 fema…  2007
    4 Adelie  Torgers…        NA         NA               NA          NA <NA>   2007
    5 Adelie  Torgers…        36.7       19.3            193        3450 fema…  2007
    6 Adelie  Torgers…        39.3       20.6            190        3650 male   2007
    # ℹ 1 more variable: bill_ratio <dbl>
  • 위 문제에서 NA 가 있는 행은 제거하고 보여줘라

    Code
    df |> 
       rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      mutate(bill_ratio=bill_length/bill_depth) |> 
      na.omit() %>% head()
    # A tibble: 6 × 9
      species island   bill_length bill_depth flipper_length body_mass_g sex    year
      <fct>   <fct>          <dbl>      <dbl>          <int>       <int> <fct> <int>
    1 Adelie  Torgers…        39.1       18.7            181        3750 male   2007
    2 Adelie  Torgers…        39.5       17.4            186        3800 fema…  2007
    3 Adelie  Torgers…        40.3       18              195        3250 fema…  2007
    4 Adelie  Torgers…        36.7       19.3            193        3450 fema…  2007
    5 Adelie  Torgers…        39.3       20.6            190        3650 male   2007
    6 Adelie  Torgers…        38.9       17.8            181        3625 fema…  2007
    # ℹ 1 more variable: bill_ratio <dbl>
  • Adelie, Chinstrap 펭귄의 각각 body_mass가 가장 작은 10개의 평균 부리길이(bill_length)를 구해서 두 평균 차이를 계산하라

    Code
    avg1 <- df |> 
       rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      filter(species=="Adelie") |> 
      arrange(body_mass_g) |> 
      slice(1:10) |> 
      summarise(bl=mean(bill_length))
    avg2 <- df |> 
       rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      filter(species=="Chinstrap") |> 
      arrange(body_mass_g) |> 
      slice(1:10) |> 
      summarise(bl=mean(bill_length))
    
    result<- abs(avg1$bl-avg2$bl)
    print(result)
    [1] 9.67
  • 부리 길이(bill_length) 중 최빈값(가장 많은 수)을 찾아라.

    Code
    df |> 
       rename(bill_length = bill_length_mm,
                 bill_depth = bill_depth_mm,
                 flipper_length = flipper_length_mm) |>
      select(bill_length) |> 
      table()  -> y
    
    names(y)[which(y==max(y))] 
    [1] "41.1"

4-5. 숙제

Note

Data : gapminder 연도별, 나라별 기대수명, 인구수, 1인당 GDP

library(gapminder) 로 데이터 불러오기

문제
  1. 2007년 대륙별 나라수는 몇 나라인가?

  2. 가장 최근 연도에서 인구수가 많은 상위 10개 나라를 뽑아서 나라별 인구수와 기대 수명을 구하라. (이때 인구수는 13.2억명, 기대수명은 73세로 단위를 맞추어라. ) )

  3. 연도별 기대수명이 가장 빠르게 증가한 나라 10개를 순서대로 나열하시오. (1952년, 2007년 비교)

  4. 2002년도 대륙별 1인당 gpd의 평균과 표준편차는 어떻게 되는가?

  5. 기대수명 데이터를 표준화(평균 0, 표준편차 1) 하라.

  6. Kuwait 를 제외하고, 1인당 gpd 데이터를 정규화(1과 0 사이로 만듦) 하라

Hint

정규화 함수 nor_minmax = function(x){ result = (x - min(x)) / (max(x) - min(x)) return(result) }

표준화 함수 nor_sd = function(x){ result = (x - mean(x)) / sd(x) return(result) }

  1. gapminder |> filter(year == 2007) |> group_by(continent) |> summarise(n= n())
  2. gapminder |> filter(year == 2007) |> arrange(-pop) |> slice(1:10) |> group_by(country) |> summarise(인구수_억명 = round(pop/100000000,1), 기대수명_세 = round(lifeExp) ) |> arrange(-인구수_억명)
  3. gapminder |> select(country, year, lifeExp) |> filter(year %in% c(1952, 2007)) |> pivot_wider(names_from = year, values_from = lifeExp) |> mutate(ratio = (2007- 1952)/(2007-1952)) |> arrange(-ratio)
  4. gapminder |> filter(year == 2002) |> group_by(continent) |> summarise(avg = mean(gdpPercap, na.rm=T), σ= sd(gdpPercap, na.rm=T))

5. Day2 (전처리 연습문제)

5-1. 유튜브 데일리 인기동영상 분석

[출처] 10주차 예상문제 (실기1 유형) (이기적 스터디 카페)

dataurl =https://raw.githubusercontent.com/Datamanim/datarepo/main/youtube/youtube.csv

  • 패키지로드, 데이터 불러오기
Code
library(tidyverse)

df<-read.csv("https://raw.githubusercontent.com/Datamanim/datarepo/main/youtube/youtube.csv")

  • Q1. 인기동영상 제작횟수가 많은 채널 상위 10개명을 출력하라 (날짜기준, 중복포함)
Code
#Q1

df%>%
  group_by(channelTitle)%>%
  summarise(n=n()) |> 
  arrange(-n) |> 
  slice(1:10)
# A tibble: 10 × 2
   channelTitle                          n
   <chr>                             <int>
 1 짤툰                                372
 2 SPOTV                               318
 3 파뿌리                              318
 4 런닝맨 - 스브스 공식 채널           313
 5 엠뚜루마뚜루 : MBC 공식 종합 채널   293
 6 장삐쭈                              283
 7 BANGTANTV                           275
 8 채널 십오야                         274
 9 이과장                              258
10 총몇명                              255

  • Q2. 논란으로 인기동영상이 된 케이스를 확인하고 싶다. dislikes수가 like 수보다 높은 동영상을 제작한 채널을 모두 출력하라
Code
#Q2

df |> 
  filter(dislikes>likes) |> 
  select(channelTitle) |> 
  distinct()
                 channelTitle
1                    핫도그TV
2                 ASMR 애정TV
3           하얀트리HayanTree
4               양팡 YangPang
5           철구형 (CHULTUBE)
6                왜냐맨하우스
7        (MUTUBE)와꾸대장봉준
8                    오메킴TV
9                      육지담
10              MapleStory_KR
11 ROAD FIGHTING CHAMPIONSHIP
12              사나이 김기훈
13          나혼자산다 STUDIO
14              Gen.G esports

  • Q3. 일요일에 인기있었던 영상들중 가장많은 영상 종류(categoryId)는 무엇인가?
Code
#Q3

df |> 
  mutate(요일 = wday(trending_date2, label=T)) |> 
  filter(요일 == "일") |> 
  filter(likes> dislikes) |> 
  group_by(categoryId) |> 
  summarise(n = n()) |> 
  arrange(-n) |> 
  select(1) |> 
  slice(1)
# A tibble: 1 × 1
  categoryId
       <int>
1         24

  • Q4. 각 요일별 인기 영상들의 categoryId는 각각 몇개 씩인지 하나의 데이터 프레임으로 표현하라
Code
#Q5

df |> 
  mutate(요일 = wday(trending_date2, label=T)) |> 
  select(categoryId, 요일) |> 
  table()
          요일
categoryId   일   월   화   수   목   금   토
        1   274  263  257  234  246  243  255
        2    99  105  119  129  128  120  119
        10  830  837  894  917  890  833  776
        15  217  215  208  207  207  187  198
        17  636  668  708  706  682  633  592
        19   91   92   89   85   92   90   87
        20  289  298  285  291  282  283  296
        22 1337 1373 1375 1333 1341 1288 1289
        23  556  594  569  566  560  568  570
        24 3096 3148 3084 3090 2954 2976 3066
        25  437  453  452  468  470  444  422
        26  363  378  394  385  375  369  364
        27  199  205  194  212  194  183  183
        28  167  160  161  165  166  171  173
        29    9   10   11   12   13   12   10

  • Q5. 댓글의 수로 (comment_count) 영상 반응에 대한 판단을 할 수 있다. viewcount대비 댓글수가 가장 높은 영상을 확인하라 (view_count값이 0인 경우는 제외한다)
Code
#Q5

df |> 
  filter(view_count != 0) |> 
  mutate(ratio = comment_count/view_count) |> 
  arrange(-ratio)|> 
  slice(1) |> 
  select(title )
                                                        title
1 60분 동안 댓글이 달리지 않으면, 영상이 삭제됩니다. (챌린지)

  • Q6. like 대비 dislike의 수가 가장 적은 영상은 무엇인가? (like, dislike 값이 0인경우는 제외한다)
Code
#Q6

df |> 
  filter(dislikes != 0 & likes != 0) |> 
  mutate(n = likes / dislikes) |> 
  arrange(-n) |> 
  slice(1) |> 
  select(title)
                                                                                                         title
1 [줌터뷰] *최초공개* 사부작즈🐰🐶의 비공식 이름은 아이라인즈? 꿀조합 티키타카 가득한 NCT 127 도영&정우의 줌터뷰

  • Q7. 가장많은 트렌드 영상을 제작한 채널의 이름은 무엇인가? (날짜기준, 중복포함)
Code
#Q7


df |> 
  group_by(channelTitle)%>%
  summarise(n=n()) |> 
  arrange(-n) |> 
  slice(1)
# A tibble: 1 × 2
  channelTitle     n
  <chr>        <int>
1 짤툰           372

  • Q8. 20회(20일)이상 인기동영상 리스트에 포함된 동영상의 숫자는?
Code
#Q8

df |> 
  group_by(title) |> 
  summarise(n = n()) |> 
  filter(n >= 20) |> 
  count()
# A tibble: 1 × 1
      n
  <int>
1    41


5-2. 넷플릭스 데이터 분석

[출처] 9주차 예상문제 (실기1 유형) (이기적 스터디 카페)

dataurl =https://raw.githubusercontent.com/Datamanim/datarepo/main/nflx/NFLX.csv

  • 패키지로드, 데이터 불러오기
Code
df <- read.csv("https://raw.githubusercontent.com/Datamanim/datarepo/main/nflx/NFLX.csv")
  • Q1. 매년 5월달의 open 가격의 평균값을 데이터프레임으로 표현하라.
Code
#Q1

library(lubridate)

df |> mutate(year = year(Date),
             month = month(Date)) |>
  filter(month == 5) |> 
  group_by(year) |> 
  summarise(평균 = mean(Open))
# A tibble: 20 × 2
    year   평균
   <dbl>  <dbl>
 1  2002   1.16
 2  2003   1.64
 3  2004   4.26
 4  2005   1.95
 5  2006   4.16
 6  2007   3.16
 7  2008   4.44
 8  2009   5.79
 9  2010  14.4 
10  2011  34.7 
11  2012  10.5 
12  2013  31.9 
13  2014  51.1 
14  2015  85.1 
15  2016  92.7 
16  2017 158.  
17  2018 330.  
18  2019 360.  
19  2020 434.  
20  2021 497.  


5-3. 날짜 다루기

To learn more about lubridate see https://lubridate.tidyverse.org/.

  • 패키지 설치, 불러오기
Code
#install.packages('lubridate')
library('lubridate')
  • 문자로 표현된 날짜를 날짜변수로 바꾸기
Code
date <- '2020-01-10'
class(date)
[1] "character"
Code
date2 <- as.Date(date)
class(date2)
[1] "Date"
  • 연, 월, 일 뽑아내기
Code
year(date)
[1] 2020
Code
month(date)
[1] 1
Code
day(date)
[1] 10
Code
ymd(date)
[1] "2020-01-10"
  • 주, 요일 뽑아내기
Code
week(date)
[1] 2
Code
wday(date)
[1] 6
Code
wday(date, label = T)
[1] 금
Levels: 일 < 월 < 화 < 수 < 목 < 금 < 토
  • 시간, 분, 초 뽑아내기
Code
now()
[1] "2024-06-29 21:39:23 KST"
Code
time <- now()
hour(time)
[1] 21
Code
minute(time)
[1] 39
Code
second(time)
[1] 23.49704
Code
ymd_hms(time)
[1] "2024-06-29 21:39:23 UTC"

5-4. 강수량 분석

[출처] 1주차 예상문제 (실기1 유형) (이기적 스터디 카페)

dataurl = https://raw.githubusercontent.com/Datamanim/datarepo/main/weather/weather2.csv

  • 패키지로드, 데이터 불러오기
Code
library(tidyverse)

df<-read.csv("https://raw.githubusercontent.com/Datamanim/datarepo/main/weather/weather2.csv")

  • Q1. 여름철(6월,7월,8월) 이화동이 수영동보다 높은 기온을 가진 시간대는 몇개인가?
Code
#Q1

library(lubridate)

df |> 
  mutate(월 = month(time),
         시간 = hour(time)) |> 
  filter(월 %in% c(6,7,8),
         이화동기온 > 수영동기온) |> 
  nrow()
[1] 1415
  • Q2. 이화동과 수영동의 최대강수량의 시간대를 각각 구하여라
Code
#Q2

df |> 
  filter(이화동강수 == max(이화동강수 ) ) |> 
  select(time)
                 time
1 2020-09-30 09:00:00
Code
df |> 
  filter(수영동강수 == max(수영동강수)) |> 
  select(time)
                 time
1 2020-07-23 12:00:00

6. Day3 (데이터 불러와서 전처리, 시각화)

To learn more about tidyr see https://tidyr.tidyverse.org/reference/pivot_longer.html/.

데이터 분석의 첫 걸음은 데이터를 불러오는 과정이다.

  1. R의 내장 데이터에서 불러오기

    data() , help(“AirPassengers”)

https://vincentarelbundock.github.io/Rdatasets/datasets.html

Code
data(AirPassengers)
AirPassengers
     Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1949 112 118 132 129 121 135 148 148 136 119 104 118
1950 115 126 141 135 125 149 170 170 158 133 114 140
1951 145 150 178 163 172 178 199 199 184 162 146 166
1952 171 180 193 181 183 218 230 242 209 191 172 194
1953 196 196 236 235 229 243 264 272 237 211 180 201
1954 204 188 235 227 234 264 302 293 259 229 203 229
1955 242 233 267 269 270 315 364 347 312 274 237 278
1956 284 277 317 313 318 374 413 405 355 306 271 306
1957 315 301 356 348 355 422 465 467 404 347 305 336
1958 340 318 362 348 363 435 491 505 404 359 310 337
1959 360 342 406 396 420 472 548 559 463 407 362 405
1960 417 391 419 461 472 535 622 606 508 461 390 432
Code
plot(AirPassengers, main = "Airline Passengers Over Time",
     xlab = "Year-Month", ylab = "Number of Passengers")

  1. 외장데이터 불러오기 (package 설치, library로 불러오기)

    gapminder : 세계 여러 국가의 인구, 경제, 건강 등의 데이터를 포함

Code
#install.packages("gapminder")
library(gapminder)

data(gapminder)
head(gapminder)
# A tibble: 6 × 6
  country     continent  year lifeExp      pop gdpPercap
  <fct>       <fct>     <int>   <dbl>    <int>     <dbl>
1 Afghanistan Asia       1952    28.8  8425333      779.
2 Afghanistan Asia       1957    30.3  9240934      821.
3 Afghanistan Asia       1962    32.0 10267083      853.
4 Afghanistan Asia       1967    34.0 11537966      836.
5 Afghanistan Asia       1972    36.1 13079460      740.
6 Afghanistan Asia       1977    38.4 14880372      786.
  1. 클릭보드(엑셀)에서 붙여넣기

    datapaste 패키지 설치 -> 엑셀에서 ctrl+c -> RStudio의 Addins에서 Paste as tribble

  1. csv 파일에서 불러오기
Code
#| eval: true

 #  read.csv ("D:/r/data/test.csv")       ## **/** 방향 주의
 #  read.csv ("D:\\r\\data\\test.csv")    ## **\\** 방향 주의
  1. 엑셀파일 불러오기 https://readxl.tidyverse.org/
Code
#| eval: true

#   install.packages('readxl')
#   library(readxl)
#   read_excel("my_file.xls")
  1. 구글시트에서 불러오기

[참고] https://googlesheets4.tidyverse.org/

Code
#install.packages("googlesheets4")
library(googlesheets4)
gs4_deauth()

df <- read_sheet("https://docs.google.com/spreadsheets/d/1V1nPp1tzOuutXFLb3G9Eyxi3qxeEhnOXUzL5_BcCQ0w/edit?gid=0#gid=0")

head(df)
# A tibble: 6 × 5
  `Student ID` `Full Name`      favourite.food     mealPlan            AGE      
         <dbl> <chr>            <chr>              <chr>               <list>   
1            1 Sunil Huffmann   Strawberry yoghurt Lunch only          <dbl [1]>
2            2 Barclay Lynn     French fries       Lunch only          <dbl [1]>
3            3 Jayendra Lyne    N/A                Breakfast and lunch <dbl [1]>
4            4 Leon Rossini     Anchovies          Lunch only          <NULL>   
5            5 Chidiegwu Dunkel Pizza              Breakfast and lunch <chr [1]>
6            6 Güvenç Attila    Ice cream          Lunch only          <dbl [1]>
  1. NA 처리하기 https://tidyr.tidyverse.org/reference/fill.html
Code
sales <- tibble::tribble(
  ~quarter, ~year, ~sales,
  "Q1",    2000,    66013,
  "Q2",      NA,    69182,
  "Q3",      NA,    53175,
  "Q4",      NA,    21001,
  "Q1",    2001,    46036,
  "Q2",      NA,    58842,
  "Q3",      NA,    44568,
  "Q4",      NA,    50197,
  "Q1",    2002,    39113,
  "Q2",      NA,    41668,
  "Q3",      NA,    30144,
  "Q4",      NA,    52897,
  "Q1",    2004,    32129,
  "Q2",      NA,    67686,
  "Q3",      NA,    31768,
  "Q4",      NA,    49094
)


# `fill()` defaults to replacing missing data from top to bottom
sales %>% fill(year, .direction = "down")
# A tibble: 16 × 3
   quarter  year sales
   <chr>   <dbl> <dbl>
 1 Q1       2000 66013
 2 Q2       2000 69182
 3 Q3       2000 53175
 4 Q4       2000 21001
 5 Q1       2001 46036
 6 Q2       2001 58842
 7 Q3       2001 44568
 8 Q4       2001 50197
 9 Q1       2002 39113
10 Q2       2002 41668
11 Q3       2002 30144
12 Q4       2002 52897
13 Q1       2004 32129
14 Q2       2004 67686
15 Q3       2004 31768
16 Q4       2004 49094
  1. NA를 평균, 중앙값으로 대체하기
Code
head(airquality)
  Ozone Solar.R Wind Temp Month Day
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
3    12     149 12.6   74     5   3
4    18     313 11.5   62     5   4
5    NA      NA 14.3   56     5   5
6    28      NA 14.9   66     5   6
Code
colSums(is.na(airquality))
  Ozone Solar.R    Wind    Temp   Month     Day 
     37       7       0       0       0       0 
Code
airquality |> 
  mutate(Ozone = ifelse(is.na(Ozone), mean(Ozone, na.rm=T), Ozone),
         Solar.R = ifelse(is.na(Ozone), median(Ozone, na.rm=T), Solar.R)) -> airquality2

colSums(is.na(airquality2))
  Ozone Solar.R    Wind    Temp   Month     Day 
      0       7       0       0       0       0 

6-1. long-form (pivot_longer)

pivot_longer : https://tidyr.tidyverse.org/reference/pivot_longer.html pivot_wider : https://tidyr.tidyverse.org/reference/pivot_wider.html

iris 데이터 : wide form 을 long form으로 만들기

Code
head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
Code
iris |> pivot_longer(cols = Sepal.Length: Petal.Width, names_to = "measure", values_to = "value") |> head()
# A tibble: 6 × 3
  Species measure      value
  <fct>   <chr>        <dbl>
1 setosa  Sepal.Length   5.1
2 setosa  Sepal.Width    3.5
3 setosa  Petal.Length   1.4
4 setosa  Petal.Width    0.2
5 setosa  Sepal.Length   4.9
6 setosa  Sepal.Width    3  

6-2. 시각화 하기

[참고 자료]https://waterfirst.quarto.pub/r_course/#/title-slide [참고 자료]https://rstudio.github.io/cheatsheets/html/data-visualization.html

ChickWeight 데이터셋:

weight: 닭의 체중 Time: 실험 시간 Chick: 닭의 고유 식별자 Diet: 실험 그룹을 나타내는 범주형 변수로, 각 닭이 어떤 종류의 식사를 받았는지를 나타냅니다.

Code
head(ChickWeight)
  weight Time Chick Diet
1     42    0     1    1
2     51    2     1    1
3     59    4     1    1
4     64    6     1    1
5     76    8     1    1
6     93   10     1    1
Code
ChickWeight |> ggplot(aes(Time, weight, col=Chick, fill=Diet))+geom_point()+
  geom_line()+
  facet_wrap(~Diet,)+
  theme(legend.position = "none")

산점도 그래프

[참고자료]https://ggplot2.tidyverse.org/index.html

Code
library(tidyverse)

ggplot(mpg, aes(cty, hwy)) +
  geom_point(mapping = aes(colour = displ)) +
  geom_smooth(formula = y ~ x, method = "lm") +
  scale_colour_viridis_c() +
  facet_grid(year ~ drv) +
  coord_fixed() +
  theme_minimal() +
  theme(panel.grid.minor = element_blank())

Color 팔레트

Code
library(RColorBrewer)
display.brewer.all()

사용법 :

scale_fill_brewer(palette=“Set1”)

scale_colour_brewer(palette=“Set1”)

[Color Pick Up](https://r-graph-gallery.com/ggplot2-color.html)

[Colorspace 패키지](https://m.blog.naver.com/regenesis90/222234511150)

[Sci-Fi](https://cran.r-project.org/web/packages/ggsci/vignettes/ggsci.html)

막대 그래프

[참고자료]https://r-charts.com/ranking/bar-plot-ggplot2/

Code
# install.packages("ggplot2")
library(ggplot2)
df <- data.frame(group = c("A", "B", "C"),
                 count = c(3, 5, 6))
ggplot(df, aes(x = group, y = count, fill=group)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = count), vjust = -1, colour = "black") +
  ylim(c(0, 6.5)) # Increase the limits of the Y-axis if needed 

Code
# install.packages("ggplot2")
library(ggplot2)

ggplot(df, aes(x = group, y = count, fill=group)) +
  geom_col() 

Boxplot 그래프

[참고자료]https://ggplot2.tidyverse.org/reference/geom_boxplot.html

Code
ggplot(mpg, aes(class, hwy)) + geom_boxplot(aes(colour = drv))

viloin 그래프

[참고자료]https://r-charts.com/es/distribucion/grafico-violin-grupo-ggplot2/

Code
# install.packages("ggplot2")
library(ggplot2)

ggplot(warpbreaks, aes(x = tension, y = breaks, fill = tension)) +
  geom_violin(trim = FALSE) +
  geom_boxplot(width = 0.07) 

Density 그래프

[참고자료]https://r-charts.com/es/distribucion/grafico-densidad-grupo-ggplot2/

Code
# Datos
set.seed(5)
x <- c(rnorm(200, mean = -2, 1.5),
       rnorm(200, mean = 0, sd = 1),
       rnorm(200, mean = 2, 1.5))
grupo <- c(rep("A", 200), rep("B", 200), rep("C", 200))
df <- data.frame(x, grupo)

# install.packages("ggplot2")
library(ggplot2)

cols <- c("#F76D5E", "#FFFFBF", "#72D8FF")

# Gráfico de densidad en ggplot2
ggplot(df, aes(x = x, fill = grupo)) +
  geom_density(alpha = 0.7) + 
  scale_fill_manual(values = cols) 

Pair 그래프

[참고자료]https://r-charts.com/es/correlacion/ggpairs/

Code
# install.packages("GGally")
library(GGally)

ggpairs(iris)  

Code
# install.packages("GGally")
library(GGally)

ggpairs(iris, columns = 1:4, aes(color = Species, alpha = 0.5),
        upper = list(continuous = "points")) 

Sankey 그래프

[참고자료]https://r-charts.com/es/flujo/diagrama-sankey-ggplot2/

Code
# install.packages("remotes")
# remotes::install_github("davidsjoberg/ggsankey")

library(ggsankey)
df <- mtcars %>%
  make_long(cyl, vs, am, gear, carb) 

# install.packages("remotes")
# remotes::install_github("davidsjoberg/ggsankey")
library(ggsankey)
# install.packages("ggplot2")
library(ggplot2)
# install.packages("dplyr")
library(dplyr) # Necesario

ggplot(df, aes(x = x, 
               next_x = next_x, 
               node = node, 
               next_node = next_node,
               fill = factor(node),
               label = node)) +
  geom_sankey(flow.alpha = 0.5, node.color = 1) +
  geom_sankey_label(size = 3.5, color = 1, fill = "white") +
  scale_fill_viridis_d() +
  theme_sankey(base_size = 16) +
  theme(legend.position = "none") 

그래프 분할하기

  • facet_grid
Code
#create data frame
df <- data.frame(team=c('A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'),
                 position=c('G', 'G', 'F', 'F', 'G', 'G', 'G', 'G'),
                 points=c(8, 14, 20, 22, 25, 29, 30, 31),
                 assists=c(10, 5, 5, 3, 8, 6, 9, 12))

ggplot(df, aes(assists, points)) +
  geom_point() +
  facet_grid(position~team)

  • facet_warp
Code
ggplot(df, aes(assists, points)) +
  geom_point() +
  facet_wrap(position~team)

Patchwork 패키지

Code
library(patchwork)

p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))

p1 + p2

Code
p3 <- ggplot(mtcars) + geom_smooth(aes(disp, qsec))
p4 <- ggplot(mtcars) + geom_bar(aes(carb))

(p1 | p2 | p3) /
      p4

논문용 Theme

Code
theme_Publication <- function(base_size=14, base_family="helvetica") {
  library(grid)
  library(ggthemes)
  (theme_foundation(base_size=base_size, base_family=base_family)
    + theme(plot.title = element_text(face = "bold",
                                      size = rel(1.2), hjust = 0.5),
            text = element_text(),
            panel.background = element_rect(colour = NA),
            plot.background = element_rect(colour = NA),
            panel.border = element_rect(colour = NA),
            axis.title = element_text(face = "bold",size = rel(1)),
            axis.title.y = element_text(angle=90,vjust =2),
            axis.title.x = element_text(vjust = -0.2),
            axis.text = element_text(), 
            axis.line = element_line(colour="black"),
            axis.ticks = element_line(),
            panel.grid.major = element_line(colour="#f0f0f0"),
            panel.grid.minor = element_blank(),
            legend.key = element_rect(colour = NA),
            legend.position = "bottom",
            legend.direction = "horizontal",
            legend.key.size= unit(0.2, "cm"),
            legend.margin = unit(0, "cm"),
            legend.title = element_text(face="italic"),
            plot.margin=unit(c(10,5,5,5),"mm"),
            strip.background=element_rect(colour="#f0f0f0",fill="#f0f0f0"),
            strip.text = element_text(face="bold")
    ))
  
}

scale_fill_Publication <- function(...){
  library(scales)
  discrete_scale("fill","Publication",manual_pal(values = c("#386cb0","#fdb462","#7fc97f","#ef3b2c","#662506","#a6cee3","#fb9a99","#984ea3","#ffff33")), ...)
  
}

scale_colour_Publication <- function(...){
  library(scales)
  discrete_scale("colour","Publication",manual_pal(values = c("#386cb0","#fdb462","#7fc97f","#ef3b2c","#662506","#a6cee3","#fb9a99","#984ea3","#ffff33")), ...)
  
}

Plotly 그래프

Code
library(ggplot2)
library(ggrepel)
library(dplyr)


temp.dat <- structure(list(Year = c("2003", "2004", "2005", "2006", "2007", 
                                    "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2003", 
                                    "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", 
                                    "2012", "2013", "2014", "2003", "2004", "2005", "2006", "2007", 
                                    "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2003", 
                                    "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", 
                                    "2012", "2013", "2014"), State = structure(c(1L, 1L, 1L, 1L, 
                                                                                 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
                                                                                 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
                                                                                 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), .Label = c("VIC", 
                                                                                                                                             "NSW", "QLD", "WA"), class = "factor"), Capex = c(5.35641472365348, 
                                                                                                                                                                                               5.76523240652641, 5.24727577535625, 5.57988239709746, 5.14246402568366, 
                                                                                                                                                                                               4.96786288162828, 5.493190785287, 6.08500616799372, 6.5092228474591, 
                                                                                                                                                                                               7.03813541623157, 8.34736513875897, 9.04992300432169, 7.15830329914056, 
                                                                                                                                                                                               7.21247045701994, 7.81373928617117, 7.76610217197542, 7.9744994967006, 
                                                                                                                                                                                               7.93734452080786, 8.29289899132255, 7.85222269563982, 8.12683746325074, 
                                                                                                                                                                                               8.61903784301649, 9.7904327253813, 9.75021175267288, 8.2950673974226, 
                                                                                                                                                                                               6.6272705639724, 6.50170524635367, 6.15609626379471, 6.43799637295979, 
                                                                                                                                                                                               6.9869551384028, 8.36305663640294, 8.31382617231745, 8.65409824343971, 
                                                                                                                                                                                               9.70529678167458, 11.3102788081848, 11.8696420977237, 6.77937303542605, 
                                                                                                                                                                                               5.51242844820827, 5.35789621712839, 4.38699327451101, 4.4925792218211, 
                                                                                                                                                                                               4.29934654081527, 4.54639175257732, 4.70040615159951, 5.04056109514957, 
                                                                                                                                                                                               5.49921208937735, 5.96590909090909, 6.18700407463007)), class = "data.frame", row.names = c(NA, 
                                                                                                                                                                                                                                                                                           -48L), .Names = c("Year", "State", "Capex"))


head(temp.dat)
  Year State    Capex
1 2003   VIC 5.356415
2 2004   VIC 5.765232
3 2005   VIC 5.247276
4 2006   VIC 5.579882
5 2007   VIC 5.142464
6 2008   VIC 4.967863
Code
library(ggplot2)
library(ggrepel)
library(dplyr)


p <- temp.dat %>%
  mutate(label = if_else(Year == max(Year), as.character(State), NA_character_)) %>%
  ggplot(aes(x = Year, y = Capex, group = State, colour = State, shape=State)) + 
  geom_line() + geom_point()+
  geom_label_repel(aes(label = label),
                   nudge_x = 1,
                   na.rm = TRUE)+
  scale_colour_Publication()+ theme_Publication()+
  theme(legend.position = "none")
p

Code
library(plotly)
ggplotly(p)

그래프 저장

Code
p

Code
ggsave("myplot.png")

p2 <- ggplotly(p)
htmlwidgets::saveWidget(p2, "myplot.html")

6. Day4 (연습 문제)

  1. 아래 사이트에서 포토 코팅/노광/현상 시간에 따른 2종의 PR 의 CD를 분석하라.

[Kaggle site]https://www.kaggle.com/datasets/waterfirst/photolithography-process-data

  1. 지도그리기

[datatoys]https://github.com/statgarten/datatoys

데이터토이에서 맛집 (datatoys::restaurant) 을 이용하여 지도에 표시하기

leaflet 패키지 이용하기 (https://bigdata-anlysis.tistory.com/34)

Code
library(datatoys)
library(tidyverse)

library(gt)
library(leaflet)


set.seed(1234)

df <- datatoys::restaurant 
gt(df |> head())
시군명 음식점명 맛집전화번호 대표음식명 소재지우편번호 소재지도로명주소 소재지지번주소 WGS84위도 WGS84경도
가평군 가평축협 한우명가 031-581-1592 푸른연잎한우명품꽃등심 12422 경기도 가평군 가평읍 달전로 19 경기도 가평군 가평읍 달전리 382-1번지 37.8158443 127.5161283
고양시 청정바지락칼국수 031-912-7676 천년초들깨수제비 10359 경기도 고양시 일산동구 일산로463번길 7 경기도 고양시 일산동구 정발산동 1148번지 37.6737073 126.7753751
고양시 양촌리아구 031-911-0430 아구탕 10218 경기도 고양시 일산서구 대화2로 152 경기도 고양시 일산서구 대화동 762-3번지 37.6719314 126.7362187
고양시 정통중화요리 남궁 031-911-3702 해물고추짬뽕, 양장피잡채 10367 경기도 고양시 일산서구 일산로 682 경기도 고양시 일산서구 대화동 2101번지 37.6820421 126.7535498
고양시 야구장농원 031-964-2884 오리진흙구이 10313 경기도 고양시 일산동구 견달산로 351 경기도 고양시 일산동구 문봉동 102-1번지 37.6971016 126.8198191
과천시 해원복집 02-504-1626 복지리 13837 경기도 과천시 별양상가로 2 경기도 과천시 별양동 1-15번지 37.4276869 126.9920020
Code
colnames(df)
[1] "시군명"           "음식점명"         "맛집전화번호"     "대표음식명"      
[5] "소재지우편번호"   "소재지도로명주소" "소재지지번주소"   "WGS84위도"       
[9] "WGS84경도"       
Code
df %>% rename(lat = WGS84위도, lng = WGS84경도) %>% 
  select(lng, lat, 음식점명) -> m

leaflet() %>%  
  addTiles() %>% 
  addMarkers(lng = as.numeric(m$lng), lat = as.numeric(m$lat), popup=m$음식점명)